#include "scope.h"
#include "hardware/structs/busctrl.h"

scope_cfg_t g_scope_cfg;

static int scope_fs_open_setting_json(struct fs_file *file, const char *name, void **priv)
{
  char buffer[400] = {0};
  char lable_buffer[32];
  int len = 0;

    if (g_scope_cfg.time_div_us >= 1000000) {
        sniprintf(lable_buffer, sizeof(lable_buffer), "%dS", g_scope_cfg.time_div_us / 1000000);
    } else if (g_scope_cfg.time_div_us >= 1000) {
        sniprintf(lable_buffer, sizeof(lable_buffer), "%dmS", g_scope_cfg.time_div_us / 1000);
    } else {
        sniprintf(lable_buffer, sizeof(lable_buffer), "%duS", g_scope_cfg.time_div_us);
    }
    len = snprintf(buffer, sizeof(buffer) - 1,
        "{\n"
            "\"Runing\":%d,\n"
            "\"Ch0Scale\":%d,\n"
            "\"Ch1Scale\":%d,\n"
            "\"SampleRate\":%d,\n"
            "\"TriggerCh\":%d,\n"
            "\"TriggerEdge\":%s,\n"
            "\"Ch0Enable\":%d,\n"
            "\"Ch1Enable\":%d,\n"
            "\"TriggerLevel\":%d,\n"
            "\"TriggerMode\":%s,\n"
            "\"TimeDivNum\":%d,\n"
            "\"MaxLength\":%d,\n"
            "\"Ch0Div\":%d,\n"
            "\"Ch1Div\":%d,\n"
            "\"TimeDivLable\":\"%s\",\n"
            "\"Ch0Gnd\":%d,\n"
            "\"Ch1Gnd\":%d,\n"
            "\"TimeDivUs\":%d,\n"
            "\"MeasureFlag\":%d\n"
        "}",
        g_scope_cfg.running,
        g_scope_cfg.ch0_scale,
        g_scope_cfg.ch1_scale,
        g_scope_cfg.rate,
        g_scope_cfg.trigger_chnl,
        (g_scope_cfg.trigger_edge == SCOPE_EDGE_RISING) ?  "\"Rising\"" :((g_scope_cfg.trigger_edge == SCOPE_EDGE_FALLING) ? "\"Falling\"" : "\"Both\""),
        g_scope_cfg.ch0_enable,
        g_scope_cfg.ch1_enable,
        g_scope_cfg.trigger_level_mv,
        (g_scope_cfg.trigger_mode == SCOPE_MODE_NORMAL) ? "\"Normal\"" : "\"Single\"",
        SCOPE_TIME_DIV_NUM,
        HTTP_FS_IV_NUM,
        g_scope_cfg.ch0_div_mv,
        g_scope_cfg.ch1_div_mv,
        lable_buffer,
        g_scope_cfg.ch0_gnd_mv,
        g_scope_cfg.ch1_gnd_mv,
        g_scope_cfg.time_div_us,
        g_scope_cfg.measure_flag
    );

    file->len = len;
    file->index = file->len;
    file->data = malloc(file->len + 1);
    file->flags = 0;
    memcpy((char *)file->data, buffer, file->len);
    return 1;
}
HTTPD_FILE_DEFINE("/setting.json", scope_fs_open_setting_json, NULL, NULL, NULL);

static void scope_proc_set_measure_flag(char *value)
{
    int bit = atoi(value);
    g_scope_cfg.measure_flag |= bit;
    log_printf("MeasureSetFlag: 0x%x\n", g_scope_cfg.measure_flag);
}
HTTPD_CGI_PARAM_DEFINE("MeasureFlagSet", scope_proc_set_measure_flag);

static void scope_proc_clear_measure_flag(char *value)
{
    int bit = atoi(value);
    g_scope_cfg.measure_flag &= (~bit);
    log_printf("MeasureSetFlag: 0x%x\n", g_scope_cfg.measure_flag);
}
HTTPD_CGI_PARAM_DEFINE("MeasureFlagClear", scope_proc_clear_measure_flag);

static void scope_proc_set_ch0_enable(char *value)
{
    if (strcmp(value, "0") == 0) {
        g_scope_cfg.ch0_enable = 0;
    }
    if (strcmp(value, "1") == 0) {
        g_scope_cfg.ch0_enable = 1;
    }
    log_printf("Ch0Enable: %d\n", g_scope_cfg.ch0_enable);
}
HTTPD_CGI_PARAM_DEFINE("Ch0Enable", scope_proc_set_ch0_enable);

static void scope_proc_set_ch1_enable(char *value)
{
    if (strcmp(value, "0") == 0) {
        g_scope_cfg.ch1_enable = 0;
    }
    if (strcmp(value, "1") == 0) {
        g_scope_cfg.ch1_enable = 1;
    }
    log_printf("Ch0Enable: %d\n", g_scope_cfg.ch1_enable);
}
HTTPD_CGI_PARAM_DEFINE("Ch1Enable", scope_proc_set_ch1_enable);

static void scope_entry_init_global(void)
{
    g_scope_cfg.rate = SCOPE_MAX_SAMPLE_RATE;
    g_scope_cfg.running = true;
    g_scope_cfg.ch0_scale = SCOPE_SCALE_1;
    g_scope_cfg.ch1_scale = SCOPE_SCALE_1;
    g_scope_cfg.ch0_div_mv = 1000;
    g_scope_cfg.ch1_div_mv = 1000;
    g_scope_cfg.ch0_gnd_mv = 0;
    g_scope_cfg.ch1_gnd_mv = -3000;
    g_scope_cfg.trigger_chnl = SCOPE_CHN_0;
    g_scope_cfg.trigger_edge = SCOPE_EDGE_RISING;
    g_scope_cfg.ch0_enable = true;
    g_scope_cfg.ch1_enable = true;
    g_scope_cfg.trigger_level_mv = 1600;
    g_scope_cfg.trigger_mode = SCOPE_MODE_NORMAL;
    g_scope_cfg.time_div_us = 1000;
}

static void scope_init(void)
{
    busctrl_hw->priority = BUSCTRL_BUS_PRIORITY_DMA_W_BITS | BUSCTRL_BUS_PRIORITY_DMA_R_BITS;

    psram_init();
    lfs_rp2040_init();

    scope_entry_init_global();
    scope_cali_init();
    scope_trigger_init();
    scope_hw_init();
    scope_snap_init();
}

static void scope_poll(void)
{
    uint32_t ms = time_us_32() / 1000;

    if (ms < 5000) {
        if ((ms / 100) & 1) {
            pca9557_gpio_set(PCA_LED1, 1);
        } else {
            pca9557_gpio_set(PCA_LED1, 0);
        }
        return;
    }
    ms = ms % 1000;
    if ((ms < 100) || (((ms > 300) && (ms < 400)))) {
        pca9557_gpio_set(PCA_LED1, 1);
    } else {
        pca9557_gpio_set(PCA_LED1, 0);
    }
    scope_hw_poll();
}

PCA9557_CLIENT_DEFINE(scope_init, scope_poll);
